use std::{
    io::{BufRead, Write},
    process::{Child, Command, Stdio},
    sync::{Arc, Mutex},
    thread,
};

// 用于管理命令执行相关状态
pub struct CommandExecutor {
    pub command: Option<Command>,
    pub command_process: Option<Arc<Mutex<Child>>>,
    pub stdout_buffer: Arc<Mutex<String>>,
    pub stderr_buffer: Arc<Mutex<String>>,
    pub stdin_pipe: Option<Box<dyn Write>>,
}
impl CommandExecutor {
    pub fn new(command: &str) -> Self {
        let command_parts: Vec<&str> = command.split_whitespace().collect();
        let command_name = "cmd";
        let args = &command_parts[0..];

        let mut command_process = Command::new(command_name);
        command_process.args(args);
        command_process.stdout(Stdio::piped());
        command_process.stderr(Stdio::piped());
        command_process.stdin(Stdio::piped());

        CommandExecutor {
            command: Some(command_process),
            command_process: None,
            stdout_buffer: Arc::new(Mutex::new(String::new())),
            stderr_buffer: Arc::new(Mutex::new(String::new())),
            stdin_pipe: None,
        }
    }
    pub fn start(&mut self) {
        if let Some(mut command) = self.command.take() {
            match command.spawn() {
                Ok(child) => {
                    let child_arc = Arc::new(Mutex::new(child));
                    self.command_process = Some(Arc::clone(&child_arc));
                    // 处理标准输出
                    let child_arc_stdout = Arc::clone(&child_arc);
                    let stdout_buffer = Arc::clone(&self.stdout_buffer);
                    thread::spawn(move || {
                        if let Some(stdout) = child_arc_stdout.lock().unwrap().stdout.take() {
                            let reader = std::io::BufReader::new(stdout);
                            for line in reader.lines() {
                                if let Ok(line) = line {
                                    println!("{}", line);
                                    let mut buffer = stdout_buffer.lock().unwrap();
                                    buffer.push_str(&line);
                                    buffer.push('\n');
                                }
                            }
                        }
                    });

                    // 处理标准错误
                    let child_arc_stderr = Arc::clone(&child_arc);
                    let stderr_buffer = Arc::clone(&self.stderr_buffer);
                    thread::spawn(move || {
                        if let Some(stderr) = child_arc_stderr.lock().unwrap().stderr.take() {
                            let reader = std::io::BufReader::new(stderr);
                            for line in reader.lines() {
                                if let Ok(line) = line {
                                    let mut buffer = stderr_buffer.lock().unwrap();
                                    buffer.push_str(&line);
                                    buffer.push('\n');
                                }
                            }
                        }
                    });
                }
                Err(e) => {
                    println!("Error: {}", e);
                }
            }
        }
    }

    pub fn get_stdout(&self) -> String {
        self.stdout_buffer.lock().unwrap().clone()
    }

    pub fn get_stderr(&self) -> String {
        self.stderr_buffer.lock().unwrap().clone()
    }

    pub fn write_stdin(&mut self, input: &str) {
        if let Some(mut stdin_pipe) = self.stdin_pipe.take() {
            stdin_pipe.write_all(input.as_bytes()).unwrap();
        }
    }

    // 判断命令是否执行结束
    pub fn is_finished(&self) -> bool {
        if let Some(command) = self.command_process.as_ref() {
            let status = command.lock().unwrap().try_wait().unwrap();
            return status.is_some();
        }
        false
    }

    pub fn kill(&mut self) {
        if let Some(command) = self.command_process.take() {
            command
                .lock()
                .unwrap()
                .kill()
                .expect("Failed to kill process");
        }
    }
}
